/*	TGDefaultsModel.m
 *	Part of ThinkGeek LED Clock
 *	http://cs.beloit.edu/~morgant/thinkgeek/
 *
 * Copyright (c)2003-2005 Tim Morgan. All rights reserved.
 * Please visit http://cs.beloit.edu/~morgant/other/license.html
 * for more information about your rights and responsibilities
 * regarding this source code.
 */

#import "TGDefaultsModel.h"

@implementation TGDefaultsModel

NSString *TGDefaultsKeyBackgroundColor				= @"backgroundColor";
NSString *TGDefaultsKeyBackgroundImageFilePath		= @"backgroundImageFilePath";
NSString *TGDefaultsKeyBackgroundStyle				= @"backgroundStyle";
NSString *TGDefaultsKeyCheckUpdatesAutomatically	= @"checkUpdatesAutomatically";
NSString *TGDefaultsKeyClockSize					= @"clockSize";
NSString *TGDefaultsKeyClockTheme					= @"clockTheme";
NSString *TGDefaultsKeyTimeFormat24Hour				= @"timeFormat24Hour";

TGDefaultsModel *defaultsModelSingleton;

#pragma mark <<initialization/singleton/deallocation>>

- (void) awakeFromNib {
	defaults = [[NSMutableDictionary alloc] initWithCapacity:15]; // a reasonable guess
	standardDefaults = [[NSMutableDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"StandardDefaults" ofType:@"plist"]];
	defaultsModelSingleton = self;
}

+ (TGDefaultsModel *) defaultsModel {
	if (defaultsModelSingleton == nil)
		[[NSException exceptionWithName:@"TGUnexpectedInvocationException"
								 reason:@"Tried to access the TGDefaultsModel singleton before it had been created."
							   userInfo:nil] raise];
	
	return defaultsModelSingleton;
}

- (void) dealloc {
	[defaults release];
	[standardDefaults release];
	[super dealloc];
}

#pragma mark -
#pragma mark <<properties>>

// could be optimized
- (NSArray *) keys {
	return [standardDefaults allKeys];
}

#pragma mark -
#pragma mark <<plug-ins>>

- (void) addStandardDefaults:(NSDictionary *)moreDefaults {
	[standardDefaults addEntriesFromDictionary:moreDefaults];
}

#pragma mark -
#pragma mark <<program constants>>

- (NSString *) version {
	return [TGStringConstants version];
}

#pragma mark -
#pragma mark <<user settings>>

- (id) defaultForKey:(NSString *)key {
	id theDefault = [defaults valueForKey:key];
	if (theDefault == nil)
		[[NSException exceptionWithName:@"TGUnknownKeyException"
								 reason:@"Tried to get a default for an unknown key."
							   userInfo:nil] raise];
	return theDefault;
}

- (id) standardDefaultForKey:(NSString *)key {
	id theDefault = [standardDefaults valueForKey:key];
	if (theDefault == nil)
		[[NSException exceptionWithName:@"TGUnknownKeyException"
								 reason:@"Tried to get the standard default for an unknown key."
							   userInfo:nil] raise];
	return theDefault;
}

- (void) setDefault:(id)newDefault forKey:(NSString *)key {
	[defaults setValue:newDefault forKey:key];
}

- (NSColor *) backgroundColor {
	return [defaults valueForKey:TGDefaultsKeyBackgroundColor];
}

- (void) setBackgroundColor:(NSColor *)newColor {
	[defaults setValue:newColor forKey:TGDefaultsKeyBackgroundColor];
}

- (NSString *) backgroundImageFilePath {
	return [defaults valueForKey:TGDefaultsKeyBackgroundImageFilePath];
}

- (void) setBackgroundImageFilePath:(NSString *)newPath {
	[defaults setValue:newPath forKey:TGDefaultsKeyBackgroundImageFilePath];
}

- (NSString *) backgroundStyle {
	return [defaults valueForKey:TGDefaultsKeyBackgroundStyle];
}

- (void) setBackgroundStyle:(NSString *)newStyle {
	[defaults setValue:newStyle forKey:TGDefaultsKeyBackgroundStyle];
}

- (BOOL) checkUpdatesAutomatically {
	return [[defaults valueForKey:TGDefaultsKeyCheckUpdatesAutomatically] boolValue];
}

- (void) setCheckUpdatesAutomatically:(BOOL)willCheck {
	[defaults setValue:[NSNumber numberWithBool:willCheck] forKey:TGDefaultsKeyCheckUpdatesAutomatically];
}

- (float) clockSize {
	return [[defaults valueForKey:TGDefaultsKeyClockSize] floatValue];
}
- (void) setClockSize:(float)newSize {
	[defaults setValue:[NSNumber numberWithFloat:newSize] forKey:TGDefaultsKeyClockSize];
}

- (NSString *) clockTheme {
	return [defaults valueForKey:TGDefaultsKeyClockTheme];
}
- (void) setClockTheme:(NSString *)newTheme {
	[defaults setValue:newTheme forKey:TGDefaultsKeyClockTheme];
}

- (BOOL) isTimeFormat24Hour {
	return [[defaults valueForKey:TGDefaultsKeyTimeFormat24Hour] boolValue];
}

- (void) setTimeFormat24Hour:(BOOL)is24Hour {
	[defaults setValue:[NSNumber numberWithBool:is24Hour] forKey:TGDefaultsKeyTimeFormat24Hour];
}

#pragma mark -
#pragma mark <<validation>>

- (BOOL) validateBackgroundStyle:(id *)objectToValidatePtr error:(NSError **)outError {
	if (*objectToValidatePtr == nil) return YES;
	if (![*objectToValidatePtr isEqualToString:[TGStringConstants backgroundStyleDefault]] &&
		![*objectToValidatePtr isEqualToString:[TGStringConstants backgroundStyleCustomColor]] &&
		![*objectToValidatePtr isEqualToString:[TGStringConstants backgroundStyleDesktop]] &&
		![*objectToValidatePtr isEqualToString:[TGStringConstants backgroundStyleCustomImage]]) {
		
		*objectToValidatePtr = [standardDefaults objectForKey:TGDefaultsKeyBackgroundStyle];
		errorInDefaults = YES;
	}
	return YES;
}

- (BOOL) validateBackgroundImageFilePath:(id *)objectToValidatePtr error:(NSError **)outError {
	NSLog(@"validate called!"); // DEBUG
	if (*objectToValidatePtr == nil) return YES;
	if ([*objectToValidatePtr isEqualToString:@""]) return YES;
	
	NSImage *testImage = [[NSImage alloc] initByReferencingFile:(*objectToValidatePtr)];
	if (testImage == nil || ![testImage isValid]) {
		*objectToValidatePtr = [standardDefaults objectForKey:TGDefaultsKeyBackgroundImageFilePath];
		errorInDefaults = YES;
	}
	
	if (testImage != nil) [testImage release];
	return YES;
}

- (BOOL) validateClockSize:(id *)objectToValidatePtr error:(NSError **)outError {
	if (*objectToValidatePtr == nil) return YES;
	if ([*objectToValidatePtr floatValue] < 0.1 || [*objectToValidatePtr floatValue] > 0.9) {
		[*objectToValidatePtr setFloatValue:[[standardDefaults objectForKey:TGDefaultsKeyClockSize] floatValue]];
		errorInDefaults = YES;
	}
	return YES;
}

#pragma mark -
#pragma mark <<error handling>>

- (BOOL) errorInDefaults {
	if (errorInDefaults) {
		errorInDefaults = NO;
		return YES;
	}
	else return NO;
}

/*- (void) setValue:(id)value forUndefinedKey:(NSString *)key {
	[defaults setValue:value forKey:key];
}

- (id) valueForUndefinedKey:(NSString *)key {
	return [defaults valueForKey:key];
}*/

@end
